﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using UnityEngine;

namespace Zhongy
{
    public class EncodeTool
    {

        public static byte[] EncodePacket(byte[] data)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    bw.Write(data.Length);
                    bw.Write(data);

                    byte[] byteArray = new byte[(int) ms.Length];
                    Buffer.BlockCopy(ms.GetBuffer(), 0, byteArray, 0, (int) ms.Length);

                    return byteArray;
                }
            }
        }

        public static byte[] DecodePacket(ref List<byte> dataCache)
        {
            if (dataCache.Count < 4)
                return null;
            else
            {
                byte[] data = new byte[dataCache.Count];
                Buffer.BlockCopy(dataCache.ToArray(), 0, data, 0, dataCache.Count);
                return data;
            }

            ////METHOD RESERVE
            {
                if (dataCache.Count < 4)
                    return null;

                using (MemoryStream ms = new MemoryStream(dataCache.ToArray()))
                {
                    using (BinaryReader br = new BinaryReader(ms))
                    {
                        int length = br.ReadInt32();
                        int dataRemainLength = (int) (ms.Length - ms.Position);

                        if (length > dataRemainLength)
                            return null;

                        byte[] data = br.ReadBytes(dataRemainLength);

                        dataCache.Clear();
                        dataCache.AddRange(br.ReadBytes(dataRemainLength));

                        return data;
                    }
                }
            }
        }

        public static byte[] EncodeMsg(SocketMsg msg)
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bw = new BinaryWriter(ms);

            //string json = "{\"MT\":17,\"mesgid\":\"1586957986029\"}";
            string json = JsonConvert.SerializeObject(msg);
            Debug.Log(json);
#if DEBUG_MODEL
            Debug.Log(string.Format("<color=green>发送消息：{0}</color>", json));
#endif

            if (!string.IsNullOrEmpty(json))
            {
                ////METHOD RESERVE
                //byte[] value = EncodeObj(json);

                byte[] value = Encoding.UTF8.GetBytes(json);
                bw.Write(value);
            }

            byte[] data = new byte[(int) ms.Length];
            Buffer.BlockCopy(ms.GetBuffer(), 0, data, 0, (int) ms.Length);
            bw.Close();
            ms.Close();
            return data;
        }

        public static SocketReceiveMsg DecodeMsg(byte[] data)
        {
            MemoryStream ms = new MemoryStream(data);
            BinaryReader br = new BinaryReader(ms);
            SocketReceiveMsg msg = new SocketReceiveMsg();

            if (ms.Length - ms.Position > 0)
            {
                byte[] valueBytes = br.ReadBytes((int) (ms.Length - ms.Position));

                {
                    string json = System.Text.Encoding.UTF8.GetString(valueBytes);
#if DEBUG_MODEL
                    Debug.Log(string.Format("<color=green>收到的消息：{0}</color>", json));
#endif
                    try
                    {
                        msg = JsonConvert.DeserializeObject<SocketReceiveMsg>(json);
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(e.Message);
                        Debug.LogError(json);
                    }
                }

                ////METHOD RESERVE
                //{
                //object value = DecodeObj(valueBytes);
                //msg = (SocketReceiveMsg) value;
                //}
            }

            br.Close();
            ms.Close();
            return msg;
        }

        public static List<SocketReceiveMsg> DecodeMsgs(byte[] data)
        {
            MemoryStream ms = new MemoryStream(data);
            BinaryReader br = new BinaryReader(ms);

            List<SocketReceiveMsg> msgLst = new List<SocketReceiveMsg>();

            if (ms.Length - ms.Position > 0)
            {
                byte[] valueBytes = br.ReadBytes((int) (ms.Length - ms.Position));

                {
                    string json = System.Text.Encoding.UTF8.GetString(valueBytes);

#if DEBUG_MODEL
                    if (json.Contains("\"MT\":19"))
                    {
                        Debug.LogError(json);
                    }

                    bool skip = false;
#if !PRINT3AND4
                    if (json.Contains("\"MT\":3") || json.Contains("\"MT\":4")) skip = true;
#endif

#if !PRINT12
                    if (json.Contains("\"MT\":12")) skip = true;
#endif
                    {
                        if (!skip)
                            Debug.Log(string.Format("<color=green>收到的消息：{0}</color>", json));
                    }
#endif

                    List<string> jsonLst = EncodeTool.GetJsonArry(json);
                    //List<string> jsonLst = EncodeTool.GetJsonArryByRegex(json);

                    foreach (var item in jsonLst)
                    {
                        SocketReceiveMsg msg = new SocketReceiveMsg();
                        try
                        {
                            msg = JsonConvert.DeserializeObject<SocketReceiveMsg>(item);
                        }
                        catch (Exception e)
                        {
                            Debug.LogError(e.Message);
                            Debug.LogError(item);
                        }

                        if (msg != null)
                            msgLst.Add(msg);
                    }
                }

                ////METHOD RESERVE
                //{
                //object value = DecodeObj(valueBytes);
                //msg = (SocketReceiveMsg) value;
                //}
            }

            br.Close();
            ms.Close();
            return msgLst;
        }

        public static byte[] EncodeObj(object value)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter bf = new BinaryFormatter();
                bf.Serialize(ms, value);
                byte[] valueBytes = new byte[ms.Length];
                Buffer.BlockCopy(ms.GetBuffer(), 0, valueBytes, 0, (int) ms.Length);
                return valueBytes;
            }
        }

        public static object DecodeObj(byte[] valueBytes)
        {
            using (MemoryStream ms = new MemoryStream(valueBytes))
            {
                BinaryFormatter bf = new BinaryFormatter();
                object value = bf.Deserialize(ms);
                return value;
            }
        }


        static List<string> result = new List<string>();
        public static List<string> GetJsonArryByRegex(string ori)
        {
           result.Clear();

            string patt = @"\{.*""MT"":\d*?,.*\}";

            MatchCollection mco = Regex.Matches(ori, patt);

            foreach (Match match in mco)
            {
//#if DEBUG_MODEL
//                Debug.Log(match.Value);
//#endif
                result.Add(match.Value.ToString());
            }

            return result;
        }


        public static List<string> GetJsonArry(string ori)
        {
            

            List<int> pos = new List<int>();

            char[] total = null;
            try
            {
                total = ori.ToCharArray();
            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
                throw;
            }

            //Debug.Log("length:" + total.Length);

            int index = 0;
            int leftCount = 0;
            int rightCount = 0;

            int leftindex = -1;
            int rightindex = -1;
            foreach (char item in total)
            {
                index++;
                if (item.Equals('{'))
                {
                    leftCount++;
                    if (leftCount == 1)
                    {
                        leftindex = index - 1;
                    }

                    //deal:     n":"1.0.0.0"}{ "Version":"1.0.0.0"}
                    //excep case:   n":"{1.0}.0.0"}{ "Version":"1.0.0.0"}-->{1.0}、{ "Version":"1.0.0.0"}
                    //{1.0}后续解析处理无效，保证后面部分消息成功解析
                    if (rightCount >= leftCount && rightCount>0)
                    {
                        rightCount = 0;
                    }
                }

                if (item.Equals('}'))
                {
                    rightCount++;

                    //deal:    { "Version":"1.0.0.0"}{"n":"1.0.0.0"
                    if (rightCount == leftCount)
                    {
                        rightindex = index - 1;
                        pos.Add(leftindex);
                        pos.Add(rightindex);

                        //Debug.Log("{ " + leftindex);
                        //Debug.Log("} " + rightindex);
                        leftindex = -1;
                        rightindex = -1;
                        leftCount = 0;
                        rightCount = 0;
                    }

                }

            }

            List<string> result = new List<string>();

            int startIndex = 0;
            int endIndex = 0;
            int length = 0;

            //Debug.LogError(ori.Length);
            //Debug.LogError(ori);

            try
            {

                for (int i = 0; i < pos.Count; i = i + 2)
                {
                    startIndex = pos[i];
                    endIndex = pos[i + 1];
                    leftCount = endIndex - startIndex + 1;

                    string item = string.Empty;

                    {
                        char[] charArry = new char[leftCount];
                        int newindex = 0;
                        for (int j = startIndex; j <= endIndex; j++)
                        {
                            charArry[newindex] = total[j];
                            newindex++;
                        }

                        item = new string(charArry);
                    }

                    result.Add(item);
                }

            }
            catch (Exception e)
            {
                Debug.LogError(e.Message);
                throw;
            }
//#if DEBUG_MODEL

//            result.ForEach((json) =>
//            {
//                bool skip = false;
//#if !PRINT3AND4
//                if (json.Contains("\"MT\":3") || json.Contains("\"MT\":4")) skip = true;
//#endif

//#if !PRINT12
//                if (json.Contains("\"MT\":12")) skip = true;
//#endif
//                {
//                    if (!skip)
//                        Debug.Log(string.Format("<color=yellow>拆其为{0}</color>", json));
//                }
//            });
//#endif

            return result;
        }

        public static int SubstringCount(string str, string substring)
        {
            if (str.Contains(substring))
            {
                string strReplaced = str.Replace(substring, "");
                return (str.Length - strReplaced.Length) / substring.Length;
            }

            return 0;
        }

        static DateTime dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, 0);
        public static long GetTimestamp(DateTime dateTime)
        {
            return (dateTime.Ticks - dt1970.Ticks) / 10000;
        }
        public static DateTime NewDate(long timestamp)
        {
            long t = dt1970.Ticks + timestamp * 10000;
            return new DateTime(t);
        }


        /// <summary>
        /// 判定协议版本
        /// game端版本大于等于client端
        /// </summary>
        /// <param name="gv">GameVersion</param>
        /// <param name="av">AppVersion</param>
        /// <returns></returns>
        public static bool  JudgeVersionValid(string gv, string av)
        {
            if (gv.Equals(av))
                return true;

            string[] gvLst = gv.Split('.');
            string[] avLst = av.Split('.');

            int gvLength = gvLst.Length;
            int avLength = avLst.Length;

            for (int i = 0; i < ((gvLength > avLength) ? gvLength : avLength); i++)
            {
                if (i + 1 > avLength) return true;
                if (i + 1 > gvLength) return false;

                int curg = TryParse(gvLst[i]);
                int cura = TryParse(avLst[i]);

                if (curg > cura)
                    return true;
            }

            return false;
        }

        private static int TryParse(string str)
        {
            int result = 0;
            int.TryParse(str, out result);

            return result;
        }

        /// <summary>
        /// 得到本机ipv4地址
        /// </summary>
        /// <returns></returns>
        public static string GetLocalIp4()
        {
            string hostname = Dns.GetHostName();
            IPAddress[] ips = Dns.GetHostAddresses(hostname);
            string LocalIP = string.Empty;
            string LocalIPV4 = string.Empty;

            if (ips.Length > 0)
            {
                LocalIP = ips[0].ToString();

                foreach (IPAddress ip in ips)
                {
                    if (ip.AddressFamily == AddressFamily.InterNetwork)
                        LocalIPV4 = ip.ToString();
                }
            }

            return LocalIPV4;
        }
    }
}
